/****************************************************** 
 *	Code by Utkarsh Sinha
 *	Based on JIFT by Jun Liu
 *	Visit http://aishack.in/ for more indepth articles and tutorials
 *	on artificial intelligence
 * Use, reuse, modify, hack, kick. Do whatever you want with
 * this code :)
 ******************************************************/

#include <opencv/cv.h>
#include <opencv/highgui.h>

#include "KeyPoint.h"
#include "Descriptor.h"

namespace my {

class SIFT
{
public:
	SIFT(IplImage* img, int octaves, int intervals,double kpDistanceThreshold);
	SIFT(const char* filename, int octaves, int intervals,double kpDistanceThreshold);
	~SIFT();

	void DoSift();

	void ShowKeypoints();
	void ShowAbsSigma();

//public:
	void GenerateLists();
	void BuildScaleSpace();
	void DetectExtrema();
	void AssignOrientations();
	void ExtractKeypointDescriptors();

	unsigned int GetKernelSize(double sigma, double cut_off=0.001);
	CvMat* BuildInterpolatedGaussianTable(unsigned int size, double sigma);
	double gaussian2D(double x, double y, double sigma);


//public:
	IplImage* m_srcImage;			// The image we're working on
	unsigned int m_numOctaves;		// The desired number of octaves
	unsigned int m_numIntervals;	// The desired number of intervals
	unsigned int m_numKeypoints;	// The number of keypoints detected

	IplImage***	m_gList;		// A 2D array to hold the different gaussian blurred images
	IplImage*** m_dogList;		// A 2D array to hold the different DoG images
	IplImage*** m_extrema;		// A 2D array to hold binary images. In the binary image, 1 = extrema, 0 = not extrema
	double**	m_absSigma;		// A 2D array to hold the sigma used to blur a particular image

	vector<Keypoint> m_keyPoints;	// Holds each keypoint's basic info
	vector<Descriptor> m_keyDescs;	// Holds each keypoint's descriptor

	int minimox;
	int minimoy;

	double kpDistanceThreshold; // limiar para evitar outliers


public:
	string handle;
	IplImage* srcHoughResult;			// The image we're working on
	IplImage* srcSIFTResult;			// The image we're working on


	void ShowKeypointsCleanImage();
	void testeHoughCircles();
	IplImage *converterPretoBraco(IplImage *img);
	IplImage * testeHarris(IplImage *orginalImage, int xValue, int yValue);

	void printKeypointsFV();
	void clearMemory();
	void compara(SIFT *probe);
	float comparaKeyPoints(Keypoint *key1,Keypoint *key2);
	double calculaFatorEscala(Descriptor * desc1,Descriptor *correspondente1,Descriptor * desc2,Descriptor *correspondente2);
	void plotaPontos(vector<int> *correspondente,SIFT *probe);
	void plotaFrame(vector<int> *correspondente,SIFT *probe, int banco);
	double calculaEscalaMedia(vector<int> *correspondente,SIFT *probe);

};
};
